home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / mtools / part01 next >
Encoding:
Internet Message Format  |  1987-08-27  |  45.2 KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i023:  MS-DOS disk tools for Unix, Part01/02
  5. Message-ID: <1247@uunet.UU.NET>
  6. Date: 28 Aug 87 13:08:31 GMT
  7. Sender: Unknown@uunet.UU.NET
  8. Organization: UUNET Communications Services, Arlington, VA
  9. Lines: 1737
  10. Approved: rs@uunet.UU.NET
  11.  
  12. Submitted-by: uiucdcs!fthood!egray
  13. Posting-number: Volume 11, Issue 23
  14. Archive-name: mtools/Part01
  15.  
  16. [  I haven't tried this stuff, but it seems useful to those who might
  17.    need it.  --r$  ]
  18.  
  19. This is a collection of MSDOS tools to allow you to read and write to
  20. MSDOS formatted diskettes from a Unix based system.  The only requirement
  21. is that your system must have floppy drive and a device driver that can
  22. handle at lease one of the disk formats used by the IBM PC.
  23.  
  24. The following MSDOS commands are emulated:
  25.  
  26. Mtool         MSDOS
  27. name        equivalent    Description
  28. -----        ----        -----------
  29. mdel        DEL/ERASE    delete a MSDOS file
  30. mdir        DIR        display a MSDOS directory
  31. mmd        MD/MKDIR    make a MSDOS sub directory
  32. mrd        RD/RMDIR    remove a MSDOS sub directory
  33. mread        COPY        read (copy) a MSDOS file to Unix
  34. mren        REN/RENAME    rename an existing MSDOS file
  35. mtype        TYPE        display contents of a MSDOS file
  36. mwrite        COPY        write (copy) a Unix file to MSDOS
  37. *        CD        change working directory
  38.  
  39.     * by use of an environmental variable
  40.  
  41. Altering your particular device driver to accept the IBM disk formats is
  42. beyond the scope of this program.
  43.  
  44. This collection of programs was written under SVR2, but the only 4.2bsd
  45. inconsistencies should be strchr/strrchr vs. index/rindex.
  46.  
  47. Emmet P. Gray                US Army, HQ III Corps & Fort Hood
  48. ...!ihnp4!uiucuxc!fthood!egray        Attn: AFZF-DE-ENV
  49.                     Directorate of Engineering & Housing
  50.                     Environmental Management Office
  51.                     Fort Hood, TX 76544-5057
  52.  
  53. #! /bin/sh
  54. # This is a shell archive, meaning:
  55. # 1. Remove everything above the #! /bin/sh line.
  56. # 2. Save the resulting text in a file.
  57. # 3. Execute the file with /bin/sh (not csh) to create:
  58. #    Readme
  59. #    Makefile
  60. #    Mdel.1
  61. #    Mdir.1
  62. #    Mmd.1
  63. #    Mrd.1
  64. #    Mread.1
  65. #    Mren.1
  66. #    Mtype.1
  67. #    Mwrite.1
  68. #    msdos.h
  69. #    convdate.c
  70. #    fixname.c
  71. #    getfat.c
  72. #    init.c
  73. #    isdir.c
  74. #    match.c
  75. #    mdel.c
  76. #    mdir.c
  77. # This archive created: Thu Jul  9 22:35:39 1987
  78. export PATH; PATH=/bin:/usr/bin:$PATH
  79. echo shar: "extracting 'Readme'" '(5399 characters)'
  80. if test -f 'Readme'
  81. then
  82.     echo shar: "will not over-write existing file 'Readme'"
  83. else
  84. sed 's/^X//' << \SHAR_EOF > 'Readme'
  85. X                MTOOLS v1.2
  86. X
  87. XThis is a collection of MSDOS tools to allow you to read and write to
  88. XMSDOS formatted diskettes from a Unix based system.
  89. X
  90. XThe following MSDOS commands are emulated:
  91. X
  92. XMtool         MSDOS
  93. Xname        equivalent    Description
  94. X-----        ----        -----------
  95. Xmdel        DEL/ERASE    delete a MSDOS file
  96. Xmdir        DIR        display a MSDOS directory
  97. Xmmd        MD/MKDIR    make a MSDOS sub directory
  98. Xmrd        RD/RMDIR    remove a MSDOS sub directory
  99. Xmread        COPY        read (copy) a MSDOS file to Unix
  100. Xmren        REN/RENAME    rename an existing MSDOS file
  101. Xmtype        TYPE        display contents of a MSDOS file
  102. Xmwrite        COPY        write (copy) a Unix file to MSDOS
  103. X*        CD        change working directory
  104. X
  105. X    * by use of the environmental variable MCWD
  106. X
  107. XThe formats of IBM PC floppy disk drives are:
  108. X
  109. X   bytes per  sectors per  tracks    number    total     disk   introduced
  110. X    sector      track     per side  of sides  capacity   size    in MSDOS
  111. X     512         8          40        1        160k      5.25      1.0
  112. X     512         9          40        1        180k      5.25      1.1
  113. X     512         8          40        2        320k      5.25      2.0
  114. X     512         9          40        2        360k      5.25      2.0
  115. X     512        15          80        2        1.2M      5.25      3.0
  116. X     512         9          80        2        720k       3.5      3.2
  117. X
  118. X
  119. XThe following are typical Unix device names for the IBM formats:
  120. X
  121. X    /dev/rflp        'generic' used first to test the media
  122. X    /dev/rflp40t8s1s    40 track 8 sector single sided
  123. X    /dev/rflp40t8s2s    40 track 8 sector double sided
  124. X    /dev/rflp40t9s1s    40 track 9 sector single sided
  125. X    /dev/rflp40t9s2s    40 track 9 sector double sided
  126. X    /dev/rflp80t15s2s    80 track 15 sector double sided
  127. X    /dev/rflp80t9s2s    3.5 inch 80 track 9 sector double sided
  128. X
  129. XThese device names are in the msdos.h file as #defines and must be edited
  130. Xto match the device names on your system.  If your device driver does not
  131. Xhandle all of the formats shown, then you should leave those particular
  132. Xdevices undefined in the msdos.h file.
  133. X
  134. XThis program can be easily customized to accept non-standard disk formats.
  135. XFor example, a popular disk format for Unix machines seems to be 80 track,
  136. Xdouble sided, 8 sector.  This doesn't conform to any of the IBM standard
  137. Xformats, but MSDOS 3.30 can be made to format virtually anything using the
  138. XDRIVER.SYS parameters in the CONFIG.SYS file.  Let's take a hypothetical
  139. Xcase of a brand X Unix machine with a 80 track, double sided, 8 sector
  140. Xdisk drive.  You could purchase an external 80 track drive for your IBM
  141. Xcompatible computer and format the drive D: under MSDOS 3.30 with the
  142. Xfollowing DRIVER.SYS parameters:
  143. X
  144. X    DEVICE=DRIVER.SYS /D:2 /T:80 /S:8 /H:2 /F:2
  145. X
  146. XThen, you would edit the init.c file to include the new non-standard
  147. Xparameters.  You might need Norton Utilities, or some other program,
  148. Xto determine the statistics of the format.  Using our example, the
  149. Xformat would have the following parameters:
  150. X
  151. X    FAT#1    sectors 1 - 3        fat_len = 3
  152. X    FAT#2    sectors 4 - 6        dir_start = 4
  153. X    DIR    sectors 7 - 13        dir_len = 7
  154. X    cluster size is 2 sectors    clus_size = 2
  155. X    there are 633 clusters        num_clus = 633
  156. X
  157. XNow, the diskette formated on your PC's external drive can be used in
  158. Xboth your PC and your Unix machine.  Obviously, that diskette could not
  159. Xbe used in other IBM compatibles, unless they too had an external 80
  160. Xtrack drive.  That means that you'd need to copy your data from a normal
  161. X40 track diskette to the 80 track diskette prior to moving it to your
  162. XUnix machine.  Likewise, you'd need to copy the 80 track diskette to a
  163. X40 track diskette to be able to move data from the Unix machine to
  164. Xanother PC.
  165. X
  166. XThe manuals are very terse... it's assumed that the reader is already
  167. Xfamiliar with MSDOS.
  168. X
  169. XThe use of the environmental variable MCWD to keep track of the current
  170. Xworking directory is a little awkward, especially since there is no
  171. X'change directory' command.  Bourne shell users will have to type two
  172. Xcommands to set their working directory, ie:
  173. X
  174. X    MCWD=/TMP
  175. X    export MCWD
  176. X
  177. XWildcards are only applied to filenames and not to directory names.
  178. XFor example '/usr/local/*.c' is appropriate, but '/usr/l*/main.c' is not.
  179. X
  180. XI really wanted to avoid the use of a 'text' mode and a 'data' mode
  181. Xwhen transferring files, but I couldn't find a better way.  It gets rather
  182. Xconfusing and it's quite possible to mess up a file if you apply the
  183. Xtext mode when it is not appropriate (ie: to a COM or EXE file).  Likewise,
  184. Xif you forget to apply the text mode (to a Unix text file) then if the
  185. Xfile is used under MSDOS, it will be missing carriage returns.  However,
  186. Xif you aren't going to use the files on your Unix system (you just
  187. Xintend to hold the files and then transfer them back to MSDOS later) then
  188. Xyou shouldn't use the text mode during either mread or mwrite.  This is
  189. Xbecause, the text mode is only useful if the files are gonna be used
  190. Xunder Unix.
  191. X
  192. XMwrite adds an EOF marker to every file (not just text files).  Mread
  193. Xignores all EOF markers.
  194. X
  195. XThe MSDOS 'copy' command had to be broken down into two separate Unix
  196. Xcommands since the MSDOS device designations (A: or C:) would be
  197. Xclumsy to implement.
  198. X
  199. XMtools is also available in versions especially written for Masscomp
  200. Xcomputers and the AT&T Unix PC 7300.
  201. X
  202. XEmmet P. Gray                US Army, HQ III Corps & Fort Hood
  203. X...!ihnp4!uiucuxc!fthood!egray        Attn: AFZF-DE-ENV
  204. X                    Directorate of Engineering & Housing
  205. X                    Environmental Management Office
  206. X                    Fort Hood, TX 76544-5057
  207. SHAR_EOF
  208. if test 5399 -ne "`wc -c < 'Readme'`"
  209. then
  210.     echo shar: "error transmitting 'Readme'" '(should have been 5399 characters)'
  211. fi
  212. fi
  213. echo shar: "extracting 'Makefile'" '(2916 characters)'
  214. if test -f 'Makefile'
  215. then
  216.     echo shar: "will not over-write existing file 'Makefile'"
  217. else
  218. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  219. X#
  220. X#       Makefile for MSDOS tools
  221. X#
  222. X
  223. XCC = cc
  224. XCFLAGS = -O
  225. XLINT = lint -c
  226. XSHAR = shar -a
  227. XBINDIR = /usr/local/bin
  228. XPROGS = mdir mread mwrite mdel mtype mmd mrd mren
  229. X
  230. XMDIR = mdir.o getfat.o init.o search.o match.o convdate.o unixname.o subdir.o \
  231. X    isdir.o
  232. XMREAD = mread.o getfat.o init.o search.o match.o unixname.o subdir.o
  233. XMWRITE = mwrite.o getfat.o init.o search.o fixname.o unixname.o putfat.o \
  234. X    subdir.o mkentry.o isdir.o
  235. XMDEL = mdel.o getfat.o init.o search.o match.o unixname.o putfat.o subdir.o
  236. XMTYPE = mtype.o getfat.o init.o search.o match.o unixname.o subdir.o
  237. XMMD = mmd.o getfat.o init.o search.o fixname.o unixname.o putfat.o subdir.o \
  238. X    mkentry.o
  239. XMRD = mrd.o getfat.o init.o search.o unixname.o putfat.o subdir.o
  240. XMREN = mren.o getfat.o init.o search.o fixname.o unixname.o putfat.c subdir.o \
  241. X    isdir.o
  242. X
  243. Xall:    $(PROGS)
  244. X
  245. Xmdir:    $(MDIR)
  246. X    $(CC) $(CFLAGS) $(MDIR) -o mdir
  247. X
  248. Xmread:    $(MREAD)
  249. X    $(CC) $(CFLAGS) $(MREAD) -o mread
  250. X
  251. Xmwrite:    $(MWRITE)
  252. X    $(CC) $(CFLAGS) $(MWRITE) -o mwrite
  253. X
  254. Xmdel:    $(MDEL)
  255. X    $(CC) $(CFLAGS) $(MDEL) -o mdel
  256. X
  257. Xmtype:    $(MTYPE)
  258. X    $(CC) $(CFLAGS) $(MTYPE) -o mtype
  259. X
  260. Xmmd:    $(MMD)
  261. X    $(CC) $(CFLAGS) $(MMD) -o mmd
  262. X
  263. Xmrd:    $(MRD)
  264. X    $(CC) $(CFLAGS) $(MRD) -o mrd
  265. X
  266. Xmren:    $(MREN)
  267. X    $(CC) $(CFLAGS) $(MREN) -o mren
  268. X
  269. Xinstall: $(PROGS)
  270. X    cp mdir $(BINDIR)/mdir
  271. X    strip $(BINDIR)/mdir
  272. X    rm mdir
  273. X#    cp Mdir.1 /usr/man/man1/mdir.1
  274. X    cp mread $(BINDIR)/mread
  275. X    strip $(BINDIR)/mread
  276. X    rm mread
  277. X#    cp Mread.1 /usr/man/man1/mread.1
  278. X    cp mwrite $(BINDIR)/mwrite
  279. X    strip $(BINDIR)/mwrite
  280. X    rm mwrite
  281. X#    cp Mwrite.1 /usr/man/man1/mwrite.1
  282. X    cp mdel $(BINDIR)/mdel
  283. X    strip $(BINDIR)/mdel
  284. X    rm mdel
  285. X#    cp Mdel.1 /usr/man/man1/mdel.1
  286. X    cp mtype $(BINDIR)/mtype
  287. X    strip $(BINDIR)/mtype
  288. X    rm mtype
  289. X#    cp Mtype.1 /usr/man/man1/mtype.1
  290. X    cp mmd $(BINDIR)/mmd
  291. X    strip $(BINDIR)/mmd
  292. X    rm mmd
  293. X#    cp Mmd.1 /usr/man/man1/mmd.1
  294. X    cp mrd $(BINDIR)/mrd
  295. X    strip $(BINDIR)/mrd
  296. X    rm mrd
  297. X#    cp Mrd.1 /usr/man/man1/mrd.1
  298. X    cp mren $(BINDIR)/mren
  299. X    strip $(BINDIR)/mren
  300. X    rm mren
  301. X#    cp Mren.1 /usr/man/man1/mren.1
  302. X
  303. Xlint:
  304. X    $(LINT) mdir.c getfat.c init.c search.c match.c convdate.c subdir.c \
  305. X    unixname.c isdir.c
  306. X    $(LINT) mread.c getfat.c init.c search.c match.c unixname.c subdir.c
  307. X    $(LINT) mwrite.c getfat.c init.c search.c fixname.c unixname.c \
  308. X    putfat.c subdir.c mkentry.c isdir.c
  309. X    $(LINT) mdel.c getfat.c init.c search.c match.c unixname.c putfat.c \
  310. X    subdir.c
  311. X    $(LINT) mtype.c getfat.c init.c search.c match.c unixname.c subdir.c
  312. X    $(LINT) mmd.c getfat.c init.c search.c fixname.c unixname.c putfat.c \
  313. X    subdir.c mkentry.c
  314. X    $(LINT) mrd.c getfat.c init.c search.c unixname.c putfat.c subdir.c
  315. X    $(LINT) mren.c getfat.c init.c search.c fixname.c unixname.c putfat.c \
  316. X    subdir.c
  317. X
  318. Xshar:
  319. X    $(SHAR) Readme Makefile Mdel.1 Mdir.1 Mmd.1 Mrd.1 Mread.1 Mren.1 \
  320. X    Mtype.1 Mwrite.1 msdos.h convdate.c fixname.c getfat.c init.c \
  321. X    isdir.c match.c mdel.c mdir.c > mtools1
  322. X    $(SHAR) mkentry.c mmd.c mrd.c mread.c mren.c mtype.c mwrite.c \
  323. X    putfat.c search.c subdir.c unixname.c > mtools2
  324. SHAR_EOF
  325. if test 2916 -ne "`wc -c < 'Makefile'`"
  326. then
  327.     echo shar: "error transmitting 'Makefile'" '(should have been 2916 characters)'
  328. fi
  329. fi
  330. echo shar: "extracting 'Mdel.1'" '(673 characters)'
  331. if test -f 'Mdel.1'
  332. then
  333.     echo shar: "will not over-write existing file 'Mdel.1'"
  334. else
  335. sed 's/^X//' << \SHAR_EOF > 'Mdel.1'
  336. X.TH MDEL 1 local
  337. X.SH NAME
  338. Xmdel \- delete a MSDOS file
  339. X.SH SYNOPSIS
  340. X.B mdel msdosfile
  341. X[
  342. X.B msdosfiles...
  343. X]
  344. X.SH DESCRIPTION
  345. X.I Mdel
  346. Xdeletes a file on a MSDOS formatted diskette.  Sub directories are supported
  347. Xwith either the '/' or '\e\' separator.  The use of the '\e\' separator
  348. Xor wildcards will require the names to be enclosed in quotes to protect
  349. Xthem from the shell.
  350. X.PP
  351. X.I Mdel
  352. Xwill ask for verification prior to removing a read\-only file.
  353. X.PP
  354. XThe environmental variable MCWD may be used to establish a current
  355. Xworking directory (relative to the MSDOS diskette).
  356. X.SH SEE ALSO
  357. Xmdir(1)
  358. X.SH BUGS
  359. XDoes not follow the MSDOS convention of allowing only one file argument.
  360. SHAR_EOF
  361. if test 673 -ne "`wc -c < 'Mdel.1'`"
  362. then
  363.     echo shar: "error transmitting 'Mdel.1'" '(should have been 673 characters)'
  364. fi
  365. fi
  366. echo shar: "extracting 'Mdir.1'" '(926 characters)'
  367. if test -f 'Mdir.1'
  368. then
  369.     echo shar: "will not over-write existing file 'Mdir.1'"
  370. else
  371. sed 's/^X//' << \SHAR_EOF > 'Mdir.1'
  372. X.TH MDIR 1 local
  373. X.SH NAME
  374. Xmdir \- display a MSDOS directory
  375. X.SH SYNOPSIS
  376. X.B mdir
  377. X[
  378. X.B -w
  379. X]
  380. X.B msdosdirectory
  381. X.PP
  382. X.B mdir
  383. X[
  384. X.B -w
  385. X]
  386. X.B  msdosfile
  387. X[
  388. X.B msdosfiles...
  389. X] 
  390. X.SH DESCRIPTION
  391. X.I Mdir
  392. Xdisplays the contents of a MSDOS formatted diskette.  Sub directories
  393. Xare supported with either the '/' or '\e\' separator.  The use of
  394. Xthe '\e\' separator or wildcards will require the names to be enclosed in
  395. Xquotes to protect them from the shell.
  396. X.PP
  397. X.I Mdir
  398. Xwill accept the following command line option:
  399. X.TP
  400. X.B w
  401. XWide output.  This option will print the file names across the page without
  402. Xdisplaying the file size or creation date.
  403. X.PP
  404. XAn error occurs if a component of the path is not a directory.
  405. X.PP
  406. XThe environmental variable MCWD may be used to establish a current
  407. Xworking directory (relative to the MSDOS diskette).
  408. X.SH SEE ALSO
  409. Xmtype(1)
  410. X.SH BUGS
  411. XDoes not follow the MSDOS convention of allowing only one directory
  412. Xargument.
  413. SHAR_EOF
  414. if test 926 -ne "`wc -c < 'Mdir.1'`"
  415. then
  416.     echo shar: "error transmitting 'Mdir.1'" '(should have been 926 characters)'
  417. fi
  418. fi
  419. echo shar: "extracting 'Mmd.1'" '(723 characters)'
  420. if test -f 'Mmd.1'
  421. then
  422.     echo shar: "will not over-write existing file 'Mmd.1'"
  423. else
  424. sed 's/^X//' << \SHAR_EOF > 'Mmd.1'
  425. X.TH MMD 1 local
  426. X.SH NAME
  427. Xmmd \- make a MSDOS sub directory
  428. X.SH SYNOPSIS
  429. X.B mmd msdosdirectory
  430. X.SH DESCRIPTION
  431. X.I Mmd
  432. Xmakes a new directory on a MSDOS formatted diskette.  Sub directories are
  433. Xsupported with either the '/' or '\e\' separator.  The use of
  434. Xthe '\e\' separator will require the directory name to be enclosed in quotes
  435. Xto protect it from the shell.
  436. X.PP
  437. XReasonable care is taken to create a valid MSDOS directory name.  If an
  438. Xinvalid name is specified,
  439. X.I mmd
  440. Xwill change the name and display the new name. 
  441. X.PP
  442. XAn error occurs if the directory already exists.
  443. X.PP
  444. XThe environmental variable MCWD may be used to establish a current
  445. Xworking directory (relative to the MSDOS diskette).
  446. X.SH SEE ALSO
  447. Xmdir(1), mrd(1)
  448. SHAR_EOF
  449. if test 723 -ne "`wc -c < 'Mmd.1'`"
  450. then
  451.     echo shar: "error transmitting 'Mmd.1'" '(should have been 723 characters)'
  452. fi
  453. fi
  454. echo shar: "extracting 'Mrd.1'" '(598 characters)'
  455. if test -f 'Mrd.1'
  456. then
  457.     echo shar: "will not over-write existing file 'Mrd.1'"
  458. else
  459. sed 's/^X//' << \SHAR_EOF > 'Mrd.1'
  460. X.TH MRD 1 local
  461. X.SH NAME
  462. Xmrd \- remove a MSDOS sub directory
  463. X.SH SYNOPSIS
  464. X.B mrd msdosdirectory
  465. X.SH DESCRIPTION
  466. X.I Mrd
  467. Xremoves a directory from a MSDOS formatted diskette.  Sub directories are
  468. Xsupported with either the '/' or '\e\' separator.  The use of
  469. Xthe '\e\' separator will require the directory name to be enclosed in quotes
  470. Xto protect it from the shell.
  471. X.PP
  472. XAn error occurs if the directory is not empty.
  473. X.PP
  474. XWildcards are not supported.
  475. X.PP
  476. XThe environmental variable MCWD may be used to establish a current
  477. Xworking directory (relative to the MSDOS diskette).
  478. X.SH SEE ALSO
  479. Xmdir(1), mmd(1)
  480. SHAR_EOF
  481. if test 598 -ne "`wc -c < 'Mrd.1'`"
  482. then
  483.     echo shar: "error transmitting 'Mrd.1'" '(should have been 598 characters)'
  484. fi
  485. fi
  486. echo shar: "extracting 'Mread.1'" '(1152 characters)'
  487. if test -f 'Mread.1'
  488. then
  489.     echo shar: "will not over-write existing file 'Mread.1'"
  490. else
  491. sed 's/^X//' << \SHAR_EOF > 'Mread.1'
  492. X.TH MREAD 1 local
  493. X.SH NAME
  494. Xmread \- read (copy) a MSDOS file to Unix
  495. X.SH SYNOPSIS
  496. X.B mread
  497. X[
  498. X.B -t
  499. X|
  500. X.B -n
  501. X]
  502. X.B msdosfile unixfile
  503. X.PP
  504. X.B mread
  505. X[
  506. X.B -t
  507. X|
  508. X.B -n
  509. X]
  510. X.B  msdosfile
  511. X[
  512. X.B msdosfiles...
  513. X]
  514. X.B unixdirectory
  515. X.SH DESCRIPTION
  516. XIn the first form, 
  517. X.I mread
  518. Xcopies the specified MSDOS file to the named Unix file.  The second form
  519. Xof the command copies multiple MSDOS files to the named Unix directory.
  520. XMSDOS sub directories are supported with either the '/' or '\e\' separator.
  521. XThe use of the '\e\' separator or wildcards will require the names to be
  522. Xenclosed in quotes to protect them from the shell.
  523. X.PP
  524. X.I Mread
  525. Xwill accept the following command line options:
  526. X.TP
  527. X.B t
  528. XText file transfer.
  529. X.I Mread
  530. Xwill translate incoming carriage return/line feeds to line feeds.
  531. X.TP
  532. X.B n
  533. XNo warning.
  534. X.I Mread
  535. Xwill not warn the user when overwriting an existing file.
  536. X.PP
  537. XIf the target file already exists, and the
  538. X.I -n
  539. Xoption is not in effect,
  540. X.I mread
  541. Xasks whether or not to overwrite the file.
  542. X.PP
  543. XThe environmental variable MCWD may be used to establish a current
  544. Xworking directory (relative to the MSDOS diskette).
  545. X.SH SEE ALSO
  546. Xmdir(1), mtype(1), mwrite(1)
  547. SHAR_EOF
  548. if test 1152 -ne "`wc -c < 'Mread.1'`"
  549. then
  550.     echo shar: "error transmitting 'Mread.1'" '(should have been 1152 characters)'
  551. fi
  552. fi
  553. echo shar: "extracting 'Mren.1'" '(938 characters)'
  554. if test -f 'Mren.1'
  555. then
  556.     echo shar: "will not over-write existing file 'Mren.1'"
  557. else
  558. sed 's/^X//' << \SHAR_EOF > 'Mren.1'
  559. X.TH MREN 1 local
  560. X.SH NAME
  561. Xmren \- rename an existing MSDOS file
  562. X.SH SYNOPSIS
  563. X.B mren sourcefile targetfile
  564. X.SH DESCRIPTION
  565. X.I Mren
  566. Xrenames an existing file on a MSDOS formatted diskette.  Sub directories are
  567. Xsupported with either the '/' or '\e\' separator.  The use of the '\e\'
  568. Xseparator or wildcards will require the names to be enclosed in quotes to
  569. Xprotect them from the shell.
  570. X.PP
  571. XReasonable care is taken to create a valid MSDOS filename.  If an invalid
  572. XMSDOS target name is specified,
  573. X.I mren
  574. Xwill change the name and prompt the user to accept or reject the new name.
  575. X.PP
  576. XThe path component of the target filename (if supplied) is ignored.  In
  577. Xother words, you may not use
  578. X.I mren
  579. Xto move a file from one sub directory to another.
  580. X.PP 
  581. X.I Mren
  582. Xmay also be used to rename directories.
  583. X.PP
  584. XThe environmental variable MCWD may be used to establish a current
  585. Xworking directory (relative to the MSDOS diskette).
  586. X.SH SEE ALSO
  587. Xmwrite(1)
  588. SHAR_EOF
  589. if test 938 -ne "`wc -c < 'Mren.1'`"
  590. then
  591.     echo shar: "error transmitting 'Mren.1'" '(should have been 938 characters)'
  592. fi
  593. fi
  594. echo shar: "extracting 'Mtype.1'" '(928 characters)'
  595. if test -f 'Mtype.1'
  596. then
  597.     echo shar: "will not over-write existing file 'Mtype.1'"
  598. else
  599. sed 's/^X//' << \SHAR_EOF > 'Mtype.1'
  600. X.TH MTYPE 1 local
  601. X.SH NAME
  602. Xmtype \- display contents of a MSDOS file
  603. X.SH SYNOPSIS
  604. X.B mtype
  605. X[
  606. X.B -t
  607. X|
  608. X.B -s
  609. X]
  610. X.B msdosfile
  611. X[
  612. X.B msdosfiles...
  613. X]
  614. X.SH DESCRIPTION
  615. X.I Mtype
  616. Xdisplays the specified MSDOS file on the screen.  MSDOS sub directories are
  617. Xsupported with either the '/' or '\e\' separator.  The use of the '\e\'
  618. Xseparator or wildcards will require the names to be enclosed in quotes to
  619. Xprotect them from the shell.
  620. X.PP
  621. X.I Mtype
  622. Xwill accept the following command line options:
  623. X.TP
  624. X.B t
  625. XText file viewing.
  626. X.I Mtype
  627. Xwill translate incoming carriage return/line feeds to line feeds.
  628. X.TP
  629. X.B s
  630. XStrip high bit.
  631. X.I Mtype
  632. Xwill strip the high bit from the data.  Useful for viewing Wordstar files.
  633. X.PP
  634. XThe environmental variable MCWD may be used to establish a current
  635. Xworking directory (relative to the MSDOS diskette).
  636. X.SH SEE ALSO
  637. Xmdir(1), mread(1)
  638. X.SH BUGS
  639. XDoes not follow the MSDOS convention of allowing only one file
  640. Xargument.
  641. SHAR_EOF
  642. if test 928 -ne "`wc -c < 'Mtype.1'`"
  643. then
  644.     echo shar: "error transmitting 'Mtype.1'" '(should have been 928 characters)'
  645. fi
  646. fi
  647. echo shar: "extracting 'Mwrite.1'" '(1294 characters)'
  648. if test -f 'Mwrite.1'
  649. then
  650.     echo shar: "will not over-write existing file 'Mwrite.1'"
  651. else
  652. sed 's/^X//' << \SHAR_EOF > 'Mwrite.1'
  653. X.TH MWRITE 1 local
  654. X.SH NAME
  655. Xmwrite \- write (copy) a Unix file to MSDOS
  656. X.SH SYNOPSIS
  657. X.B mwrite
  658. X[
  659. X.B -t
  660. X|
  661. X.B -n
  662. X]
  663. X.B unixfile msdosfile
  664. X.PP
  665. X.B mwrite
  666. X[
  667. X.B -t
  668. X|
  669. X.B -n
  670. X]
  671. X.B unixfile
  672. X[
  673. X.B unixfiles...
  674. X]
  675. X.B msdosdirectory
  676. X.SH DESCRIPTION
  677. XIn the first form, 
  678. X.I mwrite
  679. Xcopies the specified Unix file to the named MSDOS file.  The second form
  680. Xof the command copies multiple Unix files to the named MSDOS directory.
  681. XMSDOS sub directories are are supported with either the '/' or '\e\' separator.
  682. XThe use of the '\e\' separator will require the names to be enclosed in
  683. Xquotes to protect them from the shell.
  684. X.PP
  685. X.I Mwrite
  686. Xwill accept the following command line options:
  687. X.TP
  688. X.B t
  689. XText file transfer.
  690. X.I Mwrite
  691. Xwill translate incoming line feeds to carriage return/line feeds.
  692. X.TP
  693. X.B n
  694. XNo warning.
  695. X.I Mwrite
  696. Xwill not warn the user when overwriting an existing file.
  697. X.PP
  698. XIf the target file already exists, and the
  699. X.I -n
  700. Xoption is not in effect,
  701. X.I mwrite
  702. Xasks whether or not to overwrite the file.
  703. X.PP
  704. XReasonable care is taken to create a valid MSDOS filename.  If an invalid
  705. Xname is specified,
  706. X.I mwrite
  707. Xwill change the name and display the new name.
  708. X.PP
  709. XThe environmental variable MCWD may be used to establish a current
  710. Xworking directory (relative to the MSDOS diskette).
  711. X.SH SEE ALSO
  712. Xmdir(1), mread(1)
  713. SHAR_EOF
  714. if test 1294 -ne "`wc -c < 'Mwrite.1'`"
  715. then
  716.     echo shar: "error transmitting 'Mwrite.1'" '(should have been 1294 characters)'
  717. fi
  718. fi
  719. echo shar: "extracting 'msdos.h'" '(791 characters)'
  720. if test -f 'msdos.h'
  721. then
  722.     echo shar: "will not over-write existing file 'msdos.h'"
  723. else
  724. sed 's/^X//' << \SHAR_EOF > 'msdos.h'
  725. X/*
  726. X * msdos common header file
  727. X */
  728. X
  729. X#define MSECSIZ    512
  730. X#define MDIRSIZ    32
  731. X
  732. X/*
  733. X * If your device driver does not support any of the following formats,
  734. X * then leave those devices undefined.
  735. X */
  736. X
  737. X#define    FLOPPY        "/dev/rflp"
  738. X#define    FLP_40_8_1    "/dev/rflp40t8s1s"
  739. X#define    FLP_40_8_2    "/dev/rflp40t8s2s"
  740. X#define    FLP_40_9_1    "/dev/rflp40t9s1s"
  741. X#define    FLP_40_9_2    "/dev/rflp40t9s2s"
  742. X#define FLP_80_15_2    "/dev/rflp80t15s2s"
  743. X#define FLP_80_9_2    "/dev/rflp80t9s2s"
  744. X
  745. Xstruct directory {
  746. X    unsigned char    name[8];    /* file name */
  747. X    unsigned char    ext[3];        /* file extent */
  748. X    unsigned char    attr;        /* attribute byte */
  749. X    unsigned char    reserved[10];    /* ?? */
  750. X    unsigned char    time[2];        
  751. X    unsigned char    date[2];
  752. X    unsigned char    start[2];    /* starting cluster number */
  753. X    unsigned char    size[4];    /* size of the file */
  754. X};
  755. SHAR_EOF
  756. if test 791 -ne "`wc -c < 'msdos.h'`"
  757. then
  758.     echo shar: "error transmitting 'msdos.h'" '(should have been 791 characters)'
  759. fi
  760. fi
  761. echo shar: "extracting 'convdate.c'" '(1314 characters)'
  762. if test -f 'convdate.c'
  763. then
  764.     echo shar: "will not over-write existing file 'convdate.c'"
  765. else
  766. sed 's/^X//' << \SHAR_EOF > 'convdate.c'
  767. X/*
  768. X * convdate(), convtime()
  769. X */
  770. X
  771. X/*
  772. X * convert MSDOS directory datestamp to ASCII
  773. X */
  774. X
  775. Xchar *
  776. Xconvdate(date_high, date_low)
  777. Xunsigned date_high;
  778. Xunsigned date_low;
  779. X{
  780. X/*
  781. X *        hi byte     |    low byte
  782. X *    |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
  783. X *      | | | | | | | | | | | | | | | | |
  784. X *      \   7 bits    /\4 bits/\ 5 bits /
  785. X *         year +80      month     day
  786. X */
  787. X    static char buffer[9];
  788. X    unsigned char year, month_hi, month_low, day;
  789. X
  790. X    year = (date_high >> 1) + 80;
  791. X    month_hi = (date_high & 0x1) << 3;
  792. X    month_low = date_low >> 5;
  793. X    day = date_low & 0x1f;
  794. X    sprintf(buffer, "%2d-%02d-%02d", month_hi+month_low, day, year);
  795. X    return(buffer);
  796. X}
  797. X
  798. X/*
  799. X * Convert MSDOS directory timestamp to ASCII
  800. X */
  801. X
  802. Xchar *
  803. Xconvtime(time_high, time_low)
  804. Xunsigned time_high;
  805. Xunsigned time_low;
  806. X{
  807. X/*
  808. X *        hi byte     |    low byte
  809. X *    |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
  810. X *      | | | | | | | | | | | | | | | | |
  811. X *      \  5 bits /\  6 bits  /\ 5 bits /
  812. X *         hour      minutes     sec*2
  813. X */
  814. X    static char buffer[7];
  815. X    char am_pm;
  816. X    unsigned char hour, min_hi, min_low;
  817. X
  818. X    hour = time_high >> 3;
  819. X    am_pm = (hour >= 12) ? 'p' : 'a';
  820. X    if (hour > 12)
  821. X        hour = hour -12;
  822. X    if (hour == 0)
  823. X        hour = 12;
  824. X    min_hi = (time_high & 0x7) << 3;
  825. X    min_low = time_low >> 5;
  826. X    sprintf(buffer, "%2d:%02d%c", hour, min_hi+min_low, am_pm);
  827. X    return(buffer);
  828. X}
  829. SHAR_EOF
  830. if test 1314 -ne "`wc -c < 'convdate.c'`"
  831. then
  832.     echo shar: "error transmitting 'convdate.c'" '(should have been 1314 characters)'
  833. fi
  834. fi
  835. echo shar: "extracting 'fixname.c'" '(1670 characters)'
  836. if test -f 'fixname.c'
  837. then
  838.     echo shar: "will not over-write existing file 'fixname.c'"
  839. else
  840. sed 's/^X//' << \SHAR_EOF > 'fixname.c'
  841. X/*
  842. X * Convert a Unix filename to a legal MSDOS name.  Returns a pointer to
  843. X * the 'fixed' name.  Will truncate file and extension names, will
  844. X * substitute the letter 'X' for any illegal character in the name.
  845. X */
  846. X
  847. X#include <stdio.h>
  848. X#include <ctype.h>
  849. X
  850. Xchar *
  851. Xfixname(name)
  852. Xchar *name;
  853. X{
  854. X    static char *dev[8] = {"CON", "AUX", "COM1", "LPT1", "PRN", "LPT2",
  855. X    "LPT3", "NUL"};
  856. X    char *s, *temp, *ext, *malloc(), *strcpy(), *strpbrk(), *strrchr();
  857. X    int i, dot, modified;
  858. X    static char *ans;
  859. X
  860. X    temp = malloc(strlen(name)+1);
  861. X    strcpy(temp, name);
  862. X                    /* zap the leading path */
  863. X    if (s = strrchr(temp, '/'))
  864. X        temp = s+1;
  865. X    if (s = strrchr(temp, '\\'))
  866. X        temp = s+1;
  867. X
  868. X    ext = NULL;
  869. X    dot = 0;
  870. X    for (s = temp; *s; ++s) {
  871. X        if (*s == '.' && !dot) {
  872. X            dot = 1;
  873. X            *s = NULL;
  874. X            ext = s + 1;
  875. X        }
  876. X        if (islower(*s))
  877. X            *s = toupper(*s);
  878. X    }
  879. X    if (*temp == NULL) {
  880. X        temp = "X";
  881. X        printf("'%s' Null name component, using '%s.%s'\n", name, temp, ext);
  882. X    }
  883. X    for (i=0; i<8; i++) {
  884. X        if (!strcmp(temp, dev[i])) {
  885. X            *temp = 'X';
  886. X            printf("'%s' Is a device name, using '%s.%s'\n", name, temp, ext);
  887. X        }
  888. X    }
  889. X    if (strlen(temp) > 8) {
  890. X        *(temp+8) = NULL;
  891. X        printf("'%s' Name too long, using, '%s.%s'\n", name, temp, ext);
  892. X    }
  893. X    if (strlen(ext) > 3) {
  894. X        *(ext+3) = NULL;
  895. X        printf("'%s' Extension too long, using '%s.%s'\n", name, temp, ext);
  896. X    }
  897. X    modified = 0;
  898. X    while (s = strpbrk(temp, "^+=/[]:',?*\\<>|\". ")) {
  899. X        modified++;
  900. X        *s = 'X';
  901. X    }
  902. X    while (s = strpbrk(ext, "^+=/[]:',?*\\<>|\". ")) {
  903. X        modified++;
  904. X        *s = 'X';
  905. X    }
  906. X    if (modified)
  907. X        printf("'%s' Contains illegal character\(s\), using '%s.%s'\n", name, temp, ext);
  908. X    ans = malloc(12);
  909. X    sprintf(ans, "%-8.8s%-3.3s", temp, ext);
  910. X    return(ans);
  911. X}
  912. SHAR_EOF
  913. if test 1670 -ne "`wc -c < 'fixname.c'`"
  914. then
  915.     echo shar: "error transmitting 'fixname.c'" '(should have been 1670 characters)'
  916. fi
  917. fi
  918. echo shar: "extracting 'getfat.c'" '(1377 characters)'
  919. if test -f 'getfat.c'
  920. then
  921.     echo shar: "will not over-write existing file 'getfat.c'"
  922. else
  923. sed 's/^X//' << \SHAR_EOF > 'getfat.c'
  924. X/*
  925. X * Get and decode a FAT (file allocation table) entry.  The FAT entries
  926. X * are 1.5 bytes long and switch nibbles (.5 byte) according to whether
  927. X * or not the entry starts on a byte boundary.  Returns the cluster 
  928. X * number on success or -1 on failure.
  929. X */
  930. X
  931. X#include "msdos.h"
  932. X
  933. Xextern int fat_len;
  934. Xextern unsigned char *fatbuf;
  935. X
  936. Xint
  937. Xgetfat(num)
  938. Xint num;
  939. X{
  940. X/*
  941. X *    |    byte n     |   byte n+1    |   byte n+2    |
  942. X *    |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
  943. X *    | | | | | | | | | | | | | | | | | | | | | | | | |
  944. X *    |  n.0  |  n.5  | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
  945. X *        \_____  \____   \______/________/_____   /
  946. X *          ____\______\________/   _____/  ____\_/
  947. X *         /     \      \          /       /     \
  948. X *    | n+1.5 |  n.0  |  n.5  | n+2.0 | n+2.5 | n+1.0 |
  949. X *    |      FAT entry k      |    FAT entry k+1      |
  950. X */
  951. X    unsigned int fat_hi, fat_low, byte_1, byte_2;
  952. X    int start;
  953. X    static int fat;
  954. X                    /* which bytes contain the entry */
  955. X    start = num * 3 / 2;
  956. X    if (start < 0 || start+1 > (fat_len * MSECSIZ))
  957. X        return(-1);
  958. X
  959. X    byte_1 = *(fatbuf + start);
  960. X    byte_2 = *(fatbuf + start + 1);
  961. X                    /* (odd) not on byte boundary */
  962. X    if (num % 2) {
  963. X        fat_hi = (byte_2 & 0xff) << 4;
  964. X        fat_low  = (byte_1 & 0xf0) >> 4;
  965. X    }
  966. X                    /* (even) on byte boundary */
  967. X    else {
  968. X        fat_hi = (byte_2 & 0xf) << 8;
  969. X        fat_low  = byte_1 & 0xff;
  970. X    }
  971. X    fat = (fat_hi + fat_low) & 0xfff;
  972. X    return(fat);
  973. X}
  974. SHAR_EOF
  975. if test 1377 -ne "`wc -c < 'getfat.c'`"
  976. then
  977.     echo shar: "error transmitting 'getfat.c'" '(should have been 1377 characters)'
  978. fi
  979. fi
  980. echo shar: "extracting 'init.c'" '(5957 characters)'
  981. if test -f 'init.c'
  982. then
  983.     echo shar: "will not over-write existing file 'init.c'"
  984. else
  985. sed 's/^X//' << \SHAR_EOF > 'init.c'
  986. X/*
  987. X * Initialize a MSDOS diskette.  Get the media signature (1st FAT entry)
  988. X * and switch to the proper floppy disk device to match the format
  989. X * of the disk.  Sets a bunch of global variables.  Returns 0 on success,
  990. X * or 1 on failure.
  991. X */
  992. X
  993. X#include <stdio.h>
  994. X#include <ctype.h>
  995. X#include "msdos.h"
  996. X
  997. Xextern int fd, dir_len, dir_start, clus_size, fat_len, num_clus;
  998. Xextern unsigned char *fatbuf;
  999. Xextern char *mcwd;
  1000. X
  1001. Xint
  1002. Xinit(mode)
  1003. Xint mode;
  1004. X{
  1005. X    int code = 0, buflen;
  1006. X    unsigned char read_fat(), fat;
  1007. X    char *getenv(), *fixmcwd(), *malloc(), version, get_dos_ver();
  1008. X    long lseek();
  1009. X    void perror(), exit();
  1010. X
  1011. X                    /* open the 'generic' floppy */
  1012. X    if ((fd = open(FLOPPY, mode)) < 0) {
  1013. X        perror("init: open");
  1014. X        exit(1);
  1015. X    }
  1016. X                    /* read media signature (1st FAT) */
  1017. X    fat = read_fat();
  1018. X    switch(fat) {
  1019. X        case 0xfe:
  1020. X#ifndef FLP_40_8_1
  1021. X            fprintf(stderr, "40 track, 8 sector, single sided: not supported\n");
  1022. X            code = 1;
  1023. X#else FLP_40_8_1
  1024. X            dir_start = 3;
  1025. X            dir_len = 4;
  1026. X            clus_size = 1;
  1027. X            fat_len = 1;
  1028. X            num_clus = 313;
  1029. X            close(fd);
  1030. X            if ((fd = open(FLP_40_8_1, mode)) < 0) {
  1031. X                perror("init: open");
  1032. X                return(1);
  1033. X            }
  1034. X#endif FLP_40_8_1
  1035. X            break;
  1036. X        case 0xff:
  1037. X#ifndef FLP_40_8_2
  1038. X            fprintf(stderr, "40 track, 8 sector, double sided: not supported\n");
  1039. X            code = 1;
  1040. X#else FLP_40_8_2
  1041. X            dir_start = 3;
  1042. X            dir_len = 7;
  1043. X            clus_size = 2;
  1044. X            fat_len = 1;
  1045. X            num_clus = 315;
  1046. X            close(fd);
  1047. X            if ((fd = open(FLP_40_8_2, mode)) < 0) {
  1048. X                perror("init: open");
  1049. X                return(1);
  1050. X            }
  1051. X#endif FLP_40_8_2
  1052. X            break;
  1053. X        case 0xfc:
  1054. X#ifndef FLP_40_9_1
  1055. X            fprintf(stderr, "40 track, 9 sector, single sided: not supported\n");
  1056. X            code = 1;
  1057. X#else FLP_40_9_1
  1058. X            dir_start = 5;
  1059. X            dir_len = 4;
  1060. X            clus_size = 1;
  1061. X            fat_len = 2;
  1062. X            num_clus = 351;
  1063. X            close(fd);
  1064. X            if ((fd = open(FLP_40_9_1, mode)) < 0) {
  1065. X                perror("init: open");
  1066. X                return(1);
  1067. X            }
  1068. X#endif FLP_40_9_1
  1069. X            break;
  1070. X        case 0xfd:
  1071. X#ifndef FLP_40_9_2
  1072. X            fprintf(stderr, "40 track, 9 sector, double sided: not supported\n");
  1073. X            code = 1;
  1074. X#else FLP_40_9_2
  1075. X            dir_start = 5;
  1076. X            dir_len = 7;
  1077. X            clus_size = 2;
  1078. X            fat_len = 2;
  1079. X            num_clus = 354;
  1080. X            close(fd);
  1081. X            if ((fd = open(FLP_40_9_2, mode)) < 0) {
  1082. X                perror("init: open");
  1083. X                return(1);
  1084. X            }
  1085. X#endif FLP_40_9_2
  1086. X            break;
  1087. X        case 0xf9:        /* all 80 track disks */
  1088. X            version = get_dos_ver();
  1089. X            switch (version) {
  1090. X                case '0':
  1091. X                case '1':
  1092. X#ifndef FLP_80_15_2
  1093. X                    fprintf(stderr, "80 track, 15 sector, double sided: not supported\n");
  1094. X                    code = 1;
  1095. X#else FLP_80_15_2
  1096. X                    dir_start = 15;
  1097. X                    dir_len = 14;
  1098. X                    clus_size = 1;
  1099. X                    fat_len = 7;
  1100. X                    num_clus = 1193;
  1101. X                    close(fd);
  1102. X                    if ((fd = open(FLP_80_15_2, mode)) < 0) {
  1103. X                        perror("init: open");
  1104. X                        return(1);
  1105. X                    }
  1106. X#endif FLP_80_15_2
  1107. X                    break;
  1108. X                case '2':
  1109. X#ifndef FLP_80_9_2
  1110. X                    fprintf(stderr, "3.5 inch 80 track, 9 sector, double sided: not supported\n");
  1111. X                    code = 1;
  1112. X#else FLP_80_9_2
  1113. X                    dir_start = 7;
  1114. X                    dir_len = 7;
  1115. X                    clus_size = 2;
  1116. X                    fat_len = 3;
  1117. X                    num_clus = 713;
  1118. X                    close(fd);
  1119. X                    if ((fd = open(FLP_80_9_2, mode)) < 0) {
  1120. X                        perror("init: open");
  1121. X                        return(1);
  1122. X                    }
  1123. X#endif FLP_80_9_2
  1124. X                    break;
  1125. X                default:
  1126. X                    fprintf(stderr, "Unknown DOS version '%02x'\n", version);
  1127. X                    code = 1;
  1128. X                    break;
  1129. X            }
  1130. X            break;
  1131. X        default:
  1132. X            fprintf(stderr, "Unknown format '%02x'\n", fat);
  1133. X            code = 1;
  1134. X            break;
  1135. X    }
  1136. X    if (code)
  1137. X        return(1);
  1138. X
  1139. X    buflen = fat_len * MSECSIZ;
  1140. X    fatbuf = (unsigned char *) malloc(buflen);
  1141. X    move(1);
  1142. X                    /* read the FAT sectors */
  1143. X    if (read(fd, fatbuf, buflen) != buflen) {
  1144. X        perror("init: read");
  1145. X        exit(1);
  1146. X    }
  1147. X                    /* set dir_chain to root directory */
  1148. X    reset_dir();
  1149. X                    /* get Current Working Directory */
  1150. X    mcwd = fixmcwd(getenv("MCWD"));
  1151. X                    /* test it out.. */
  1152. X    if (subdir("")) {
  1153. X        fprintf(stderr, "Environmental variable MCWD needs updating\n");
  1154. X        exit(1);
  1155. X    }
  1156. X    return(0);
  1157. X}
  1158. X
  1159. X/*
  1160. X * Move the read/write head to the next location.  Tries to optimize
  1161. X * the movement by moving relative to current location.  The argument
  1162. X * is a logical sector number.  All errors are fatal.
  1163. X */
  1164. X
  1165. Xmove(sector)
  1166. Xint sector;
  1167. X{
  1168. X    long cur_loc, next, lseek();
  1169. X    void exit(), perror();
  1170. X                    /* get current location */
  1171. X    if ((cur_loc = lseek(fd, 0L, 1)) < 0) {
  1172. X        perror("move: lseek");
  1173. X        exit(1);
  1174. X    }
  1175. X    next = (long) (MSECSIZ * sector) - cur_loc;
  1176. X                    /* we're already there */
  1177. X    if (next == 0L)
  1178. X        return;
  1179. X                    /* move to next location */
  1180. X    if (lseek(fd, next, 1) < 0) {
  1181. X        perror("move: lseek");
  1182. X        exit(1);
  1183. X    }
  1184. X    return;
  1185. X}
  1186. X
  1187. X/*
  1188. X * Fix MCWD to be a proper directory name.  Always has a leading separator.
  1189. X * Never has a trailing separator (unless it is the path itself).
  1190. X */
  1191. X
  1192. Xchar *
  1193. Xfixmcwd(dirname)
  1194. Xchar *dirname;
  1195. X{
  1196. X    char *s, *malloc(), *strcpy(), *strcat();
  1197. X    static char *ans;
  1198. X
  1199. X    ans = malloc(strlen(dirname)+2);
  1200. X                    /* add a leading separator */
  1201. X    if (*dirname != '/' && *dirname != '\\') {
  1202. X        strcpy(ans, "/");
  1203. X        strcat(ans, dirname);
  1204. X    }
  1205. X    else
  1206. X        strcpy(ans, dirname);
  1207. X                    /* translate to upper case */
  1208. X    for (s = ans; *s; ++s) {
  1209. X        if (islower(*s))
  1210. X            *s = toupper(*s);
  1211. X    }
  1212. X                    /* if separator alone */
  1213. X    if (strlen(ans) == 1)
  1214. X        return(ans);
  1215. X                    /* zap the trailing separator */
  1216. X    s--;
  1217. X    if (*s == '/' || *s == '\\')
  1218. X        *s = NULL;
  1219. X    return(ans);
  1220. X}
  1221. X
  1222. X/*
  1223. X * Read the first byte of the FAT table.  This code serves as a media
  1224. X * signature for the diskette.
  1225. X */
  1226. X
  1227. Xunsigned char
  1228. Xread_fat()
  1229. X{
  1230. X    unsigned char buf[MSECSIZ];
  1231. X    static unsigned char ans;
  1232. X                    /* move to boot sector */
  1233. X    if (lseek(fd, (long) MSECSIZ, 0) < 0) {
  1234. X        perror("init: lseek");
  1235. X        exit(1);
  1236. X    }
  1237. X                    /* read the first FAT sector */
  1238. X    if (read(fd, buf, MSECSIZ) != MSECSIZ) {
  1239. X        perror("init: read");
  1240. X        exit(1);
  1241. X    }
  1242. X    ans = *buf;
  1243. X    return(ans);
  1244. X}
  1245. X
  1246. X/*
  1247. X * Read the Boot Sector to figure out the DOS version.
  1248. X */
  1249. X
  1250. Xchar
  1251. Xget_dos_ver()
  1252. X{
  1253. X    unsigned char bootbuf[MSECSIZ];
  1254. X    static char ans;
  1255. X                    /* move to boot sector */
  1256. X    if (lseek(fd, 0L, 0) < 0) {
  1257. X        perror("init: lseek");
  1258. X        exit(1);
  1259. X    }
  1260. X                    /* read the boot sector */
  1261. X    if (read(fd, bootbuf, MSECSIZ) != MSECSIZ) {
  1262. X        perror("init: read");
  1263. X        exit(1);
  1264. X    }
  1265. X    ans = *(bootbuf+10);
  1266. X    return(ans);
  1267. X}
  1268. SHAR_EOF
  1269. if test 5957 -ne "`wc -c < 'init.c'`"
  1270. then
  1271.     echo shar: "error transmitting 'init.c'" '(should have been 5957 characters)'
  1272. fi
  1273. fi
  1274. echo shar: "extracting 'isdir.c'" '(917 characters)'
  1275. if test -f 'isdir.c'
  1276. then
  1277.     echo shar: "will not over-write existing file 'isdir.c'"
  1278. else
  1279. sed 's/^X//' << \SHAR_EOF > 'isdir.c'
  1280. X/*
  1281. X * Test to see if a filename is a directory.  Subdir() has to be
  1282. X * run first...  Returns 1 if true.
  1283. X */
  1284. X
  1285. X#include <stdio.h>
  1286. X#include "msdos.h"
  1287. X
  1288. Xextern int dir_entries;
  1289. X
  1290. Xint
  1291. Xisdir(path)
  1292. Xchar *path;
  1293. X{
  1294. X    int entry;
  1295. X    char *newname, *unixname(), *strncpy(), name[9], ext[4];
  1296. X    struct directory *dir, *search();
  1297. X                    /* no path */
  1298. X    if (*path == NULL)
  1299. X        return(0);
  1300. X
  1301. X    for (entry=0; entry<dir_entries; entry++) {
  1302. X        dir = search(entry);
  1303. X                    /* if empty */
  1304. X        if (dir->name[0] == NULL)
  1305. X            break;
  1306. X                    /* if erased */
  1307. X        if (dir->name[0] == 0xe5)
  1308. X            continue;
  1309. X                    /* skip if not a directory */
  1310. X        if (!(dir->attr & 0x10))
  1311. X            continue;
  1312. X        strncpy(name, dir->name, 8);
  1313. X        name[8] = NULL;
  1314. X        strncpy(ext, dir->ext, 3);
  1315. X        ext[3] = NULL;
  1316. X        newname = unixname(name, ext);
  1317. X        if (!strcmp(newname, path))
  1318. X            return(1);
  1319. X    }
  1320. X                    /* if "." or ".." fails, then root */
  1321. X    if (!strcmp(path, ".") || !strcmp(path, ".."))
  1322. X        return(1);
  1323. X    return(0);
  1324. X}
  1325. SHAR_EOF
  1326. if test 917 -ne "`wc -c < 'isdir.c'`"
  1327. then
  1328.     echo shar: "error transmitting 'isdir.c'" '(should have been 917 characters)'
  1329. fi
  1330. fi
  1331. echo shar: "extracting 'match.c'" '(1894 characters)'
  1332. if test -f 'match.c'
  1333. then
  1334.     echo shar: "will not over-write existing file 'match.c'"
  1335. else
  1336. sed 's/^X//' << \SHAR_EOF > 'match.c'
  1337. X/*
  1338. X * Do shell-style pattern matching for '?', '\', '[..]', and '*' wildcards.
  1339. X * Not idiot proof!  Returns 1 if match, 0 if not.
  1340. X *
  1341. X * Ideas for this routine were taken from a program by Rich Salz, mirror!rs
  1342. X */
  1343. X
  1344. X#include <stdio.h>
  1345. X
  1346. Xint
  1347. Xmatch(s, p)
  1348. Xchar *s;                /* string to match */
  1349. Xchar *p;                /* pattern */
  1350. X{
  1351. X    int matched, reverse;
  1352. X    char first, last;
  1353. X
  1354. X    for ( ; *p != NULL; s++, p++) {
  1355. X        switch (*p) {
  1356. X                    /* Literal match with next character */
  1357. X        case '\\':
  1358. X            p++;
  1359. X        default:
  1360. X            if (*s != *p)
  1361. X                return(0);
  1362. X            break;
  1363. X                    /* match any one character */
  1364. X        case '?':
  1365. X            if (*s == NULL)
  1366. X                return(0);
  1367. X            break;
  1368. X                    /* match everything */
  1369. X        case '*':
  1370. X                    /* if last char in pattern */
  1371. X            if (*++p == NULL)
  1372. X                return(1);
  1373. X                    /* search for next char in pattern */
  1374. X            matched = 0;
  1375. X            while (*s != NULL) {
  1376. X                if (*s == *p) {
  1377. X                    matched = 1;
  1378. X                    if (!strcmp(s+1,p+1))
  1379. X                        break;
  1380. X                }
  1381. X                s++;
  1382. X            }
  1383. X            if (!matched)
  1384. X                return(0);
  1385. X            s--;
  1386. X            p--;
  1387. X            break;
  1388. X                    /* match range of characters */
  1389. X        case '[':
  1390. X            first = NULL;
  1391. X            matched = 0;
  1392. X            reverse = 0;
  1393. X            while (*++p != ']') {
  1394. X                if (*p == '^') {
  1395. X                    reverse = 1;
  1396. X                    p++;
  1397. X                }
  1398. X                first = *p;
  1399. X                if (first == ']' || first == NULL) {
  1400. X                    fprintf(stderr, "match: Malformed regular expression\n");
  1401. X                    return(0);
  1402. X                }
  1403. X                    /* if 2nd char is '-' */
  1404. X                if (*(p+1) == '-') {
  1405. X                    p++;
  1406. X                    /* set last to 3rd char ... */
  1407. X                    last = *++p;
  1408. X                    if (last == ']' || last == NULL) {
  1409. X                        fprintf(stderr, "match: Malformed regular expression\n");
  1410. X                        return(0);
  1411. X                    }
  1412. X                    /* test the range of values */
  1413. X                    if (*s>=first && *s<=last) {
  1414. X                        matched = 1;
  1415. X                        p++;
  1416. X                        break;
  1417. X                    }
  1418. X                    return(0);
  1419. X                }
  1420. X                if (*s == *p)
  1421. X                    matched = 1;
  1422. X            }
  1423. X            if (matched && reverse)
  1424. X                return(0);
  1425. X            if (!matched)
  1426. X                return(0);
  1427. X            break;
  1428. X        }
  1429. X    }
  1430. X                    /* string ended prematurely ? */
  1431. X    if (*s != NULL)
  1432. X        return(0);
  1433. X    else
  1434. X        return(1);
  1435. X}
  1436. SHAR_EOF
  1437. if test 1894 -ne "`wc -c < 'match.c'`"
  1438. then
  1439.     echo shar: "error transmitting 'match.c'" '(should have been 1894 characters)'
  1440. fi
  1441. fi
  1442. echo shar: "extracting 'mdel.c'" '(2580 characters)'
  1443. if test -f 'mdel.c'
  1444. then
  1445.     echo shar: "will not over-write existing file 'mdel.c'"
  1446. else
  1447. sed 's/^X//' << \SHAR_EOF > 'mdel.c'
  1448. X/*
  1449. X * Delete a MSDOS file
  1450. X *
  1451. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  1452. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  1453. X *                     Directorate of Engineering & Housing
  1454. X *                     Environmental Management Office
  1455. X *                     Fort Hood, TX 76544-5057
  1456. X */
  1457. X
  1458. X#include <stdio.h>
  1459. X#include "msdos.h"
  1460. X#define VERBOSE
  1461. X
  1462. Xint fd;                /* the file descriptor for the floppy */
  1463. Xint dir_start;            /* starting sector for directory */
  1464. Xint dir_len;            /* length of directory (in sectors) */
  1465. Xint dir_entries;        /* number of directory entries */
  1466. Xint dir_chain[25];        /* chain of sectors in directory */
  1467. Xint clus_size;            /* cluster size (in sectors) */
  1468. Xint fat_len;            /* length of FAT table (in sectors) */
  1469. Xint num_clus;            /* number of available clusters */
  1470. Xunsigned char *fatbuf;        /* the File Allocation Table */
  1471. Xchar *mcwd;            /* the Current Working Directory */
  1472. X
  1473. Xmain(argc, argv)
  1474. Xint argc;
  1475. Xchar *argv[];
  1476. X{
  1477. X    int i, ismatch, entry, start, nogo, subdir();
  1478. X    char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
  1479. X    char *strncpy(), *getpath(), *pathname, ans[10];
  1480. X    void exit();
  1481. X    struct directory *dir, *search();
  1482. X
  1483. X    if (init(2)) {
  1484. X        fprintf(stderr, "mdel: Cannot initialize diskette\n");
  1485. X        exit(1);
  1486. X    }
  1487. X
  1488. X    if (argc < 2) {
  1489. X        fprintf(stderr, "Usage: mdel <MSDOS file> [<MSDOS files...>]\n");
  1490. X        exit(1);
  1491. X    }
  1492. X
  1493. X    for (i=1; i<argc; i++) {
  1494. X        filename = getname(argv[i]);
  1495. X        pathname = getpath(argv[i]);
  1496. X        if (subdir(pathname))
  1497. X            continue;
  1498. X        nogo = 0;
  1499. X        ismatch = 0;
  1500. X        for (entry=0; entry<dir_entries; entry++) {
  1501. X            dir = search(entry);
  1502. X                    /* if empty */
  1503. X            if (dir->name[0] == NULL)
  1504. X                break;
  1505. X                    /* if erased */
  1506. X            if (dir->name[0] == 0xe5)
  1507. X                continue;
  1508. X                    /* if dir or volume lable */
  1509. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  1510. X                continue;
  1511. X            strncpy(tname, dir->name, 8);
  1512. X            strncpy(text, dir->ext, 3);
  1513. X            newfile = unixname(tname, text);
  1514. X                    /* see it if matches the pattern */
  1515. X            if (match(newfile, filename)) {
  1516. X#ifdef VERBOSE
  1517. X                printf("Removing %s\n", newfile);
  1518. X#endif
  1519. X                ismatch = 1;
  1520. X                if (dir->attr & 0x01) {
  1521. X                    while (!nogo) {
  1522. X                        printf("mdel: '%s' is read only, erase anyway (y/n) ? ", newfile);
  1523. X                        gets(ans);
  1524. X                        if (ans[0] == 'y' || ans[0] == 'Y')
  1525. X                            break;
  1526. X                        if (ans[0] == 'n' || ans[0] == 'N')
  1527. X                            nogo = 1;
  1528. X                    }
  1529. X                    if (nogo)
  1530. X                        continue;
  1531. X                }
  1532. X                start = dir->start[1]*0x100 + dir->start[0];
  1533. X                zapit(start);
  1534. X                dir->name[0] = 0xe5;
  1535. X                writedir(entry, dir);
  1536. X            }
  1537. X        }
  1538. X        if (!ismatch) {
  1539. X            fprintf(stderr, "mdel: File '%s' not found\n", filename);
  1540. X            continue;
  1541. X        }
  1542. X    }
  1543. X                    /* update the FAT sectors */
  1544. X    writefat();
  1545. X    close(fd);
  1546. X    exit(0);
  1547. X}
  1548. SHAR_EOF
  1549. if test 2580 -ne "`wc -c < 'mdel.c'`"
  1550. then
  1551.     echo shar: "error transmitting 'mdel.c'" '(should have been 2580 characters)'
  1552. fi
  1553. fi
  1554. echo shar: "extracting 'mdir.c'" '(4372 characters)'
  1555. if test -f 'mdir.c'
  1556. then
  1557.     echo shar: "will not over-write existing file 'mdir.c'"
  1558. else
  1559. sed 's/^X//' << \SHAR_EOF > 'mdir.c'
  1560. X/*
  1561. X * Display a MSDOS directory
  1562. X *
  1563. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  1564. X * ...!ihnp4!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  1565. X *                     Directorate of Engineering & Housing
  1566. X *                     Environmental Management Office
  1567. X *                     Fort Hood, TX 76544-5057
  1568. X */
  1569. X
  1570. X#include <stdio.h>
  1571. X#include "msdos.h"
  1572. X
  1573. Xint fd;                /* the file descriptor for the floppy */
  1574. Xint dir_start;            /* starting sector for directory */
  1575. Xint dir_len;            /* length of directory (in sectors) */
  1576. Xint dir_entries;        /* number of directory entries */
  1577. Xint dir_chain[25];        /* chain of sectors in directory */
  1578. Xint clus_size;            /* cluster size (in sectors) */
  1579. Xint fat_len;            /* length of FAT table (in sectors) */
  1580. Xint num_clus;            /* number of available clusters */
  1581. Xunsigned char *fatbuf;        /* the File Allocation Table */
  1582. Xchar *mcwd;            /* the current working directory */
  1583. X
  1584. Xmain(argc, argv)
  1585. Xint argc;
  1586. Xchar *argv[];
  1587. X{
  1588. X    int i, entry, files, blocks, subdir(), fargn, wide;
  1589. X    long size;
  1590. X    char name[9], ext[4], *date, *time, *convdate(), *convtime();
  1591. X    char *strncpy(), *dirname, *getname(), *getpath(), *pathname, sep;
  1592. X    char *newfile, *filename, *malloc(), *unixname(), volume[12];
  1593. X    char *strcpy(), *strcat();
  1594. X    void exit();
  1595. X    struct directory *dir, *search();
  1596. X
  1597. X    if (init(0)) {
  1598. X        fprintf(stderr, "mdir: Cannot initialize diskette\n");
  1599. X        exit(1);
  1600. X    }
  1601. X                    /* find the volume label */
  1602. X    reset_dir();
  1603. X    for (entry=0; entry<dir_entries; entry++) {
  1604. X        dir = search(entry);
  1605. X        strncpy(name, dir->name, 8);
  1606. X        strncpy(ext, dir->ext, 3);
  1607. X                    /* if empty */
  1608. X        if (dir->name[0] == NULL)
  1609. X            break;
  1610. X                    /* if not volume label */
  1611. X        if (!(dir->attr & 0x08))
  1612. X            continue;
  1613. X        strcpy(volume, name);
  1614. X        strcat(volume, ext);
  1615. X        break;
  1616. X    }
  1617. X    if (volume[0] == NULL)
  1618. X        printf(" Volume in drive has no label\n");
  1619. X    else
  1620. X        printf(" Volume in drive is %s\n", volume);
  1621. X    fargn = 1;
  1622. X    wide = 0;
  1623. X                    /* first argument number */
  1624. X    if (argc > 1) {
  1625. X        if (!strcmp(argv[1], "-w")) {
  1626. X            wide = 1;
  1627. X            fargn = 2;
  1628. X        }
  1629. X    }
  1630. X                    /* fake an argument */
  1631. X    if (argc == fargn) {
  1632. X        argv[argc] = ".";
  1633. X        argc++;
  1634. X    }
  1635. X    files = 0;
  1636. X    for (i=fargn; i<argc; i++) {
  1637. X        filename = getname(argv[i]);
  1638. X        pathname = getpath(argv[i]);
  1639. X                    /* move to first guess subdirectory */
  1640. X                    /* required by isdir() */
  1641. X        if (subdir(pathname))
  1642. X            continue;
  1643. X        if (isdir(filename)) {
  1644. X            dirname = malloc(strlen(argv[i])+1);
  1645. X            strcpy(dirname, pathname);
  1646. X            if (strcmp(pathname,"/") && strcmp(pathname, "\\")) {
  1647. X                if (*pathname != NULL)
  1648. X                    strcat(dirname, "/");
  1649. X            }
  1650. X            strcat(dirname, filename);
  1651. X                    /* move to real subdirectory */
  1652. X            if (subdir(dirname))
  1653. X                continue;
  1654. X            filename = "*";
  1655. X        }
  1656. X        if (*filename == NULL)
  1657. X            filename = "*";
  1658. X        if (*dirname == '/' || *dirname == '\\')
  1659. X            printf(" Directory for %s\n\n", dirname);
  1660. X        else if (!strcmp(dirname, "."))
  1661. X            printf(" Directory for %s\n\n", mcwd);
  1662. X        else {
  1663. X            if (strlen(mcwd) == 1 || !strlen(dirname))
  1664. X                sep = NULL;
  1665. X            else
  1666. X                sep = '/';
  1667. X            printf(" Directory for %s%c%s\n\n", mcwd, sep, dirname);
  1668. X        }
  1669. X        for (entry=0; entry<dir_entries; entry++) {
  1670. X            dir = search(entry);
  1671. X            strncpy(name, dir->name, 8);
  1672. X            strncpy(ext, dir->ext, 3);
  1673. X            newfile = unixname(name, ext);
  1674. X                    /* if empty */
  1675. X            if (dir->name[0] == NULL)
  1676. X                break;
  1677. X                    /* if erased */
  1678. X            if (dir->name[0] == 0xe5)
  1679. X                continue;
  1680. X                    /* if a volume label */
  1681. X            if (dir->attr & 0x08)
  1682. X                continue;
  1683. X            if (!match(newfile, filename))
  1684. X                continue;
  1685. X            files++;
  1686. X            if (wide && files != 1) {
  1687. X                if (!((files-1) % 5))
  1688. X                    putchar('\n');
  1689. X            }
  1690. X            date = convdate(dir->date[1], dir->date[0]);
  1691. X            time = convtime(dir->time[1], dir->time[0]);
  1692. X            size = dir->size[2]*0x10000 + dir->size[1]*0x100 + dir->size[0];
  1693. X                    /* is a subdirectory */
  1694. X            if (dir->attr & 0x10) {
  1695. X                if (wide)
  1696. X                    printf("%-15.15s", name);
  1697. X                else
  1698. X                    printf("%8s     <DIR>      %s  %s\n", name, date, time);
  1699. X                continue;
  1700. X            }
  1701. X            if (wide)
  1702. X                printf("%-9.9s%-6.6s", name, ext);
  1703. X            else
  1704. X                printf("%8s %3s %8d   %s  %s\n", name, ext, size, date, time);
  1705. X        }
  1706. X        if (argc > 2)
  1707. X            putchar('\n');
  1708. X    }
  1709. X    blocks = getfree() * MSECSIZ;
  1710. X    if (!files)
  1711. X        printf("File '%s' not found\n", filename);
  1712. X    else
  1713. X        printf("     %3d File(s)     %6ld bytes free\n", files, blocks);
  1714. X    close(fd);
  1715. X    exit(0);
  1716. X}
  1717. X
  1718. X/*
  1719. X * Get the amount of free space on the diskette
  1720. X */
  1721. X
  1722. Xint getfree()
  1723. X{
  1724. X    int i;
  1725. X    static int total;
  1726. X
  1727. X    total = 0;
  1728. X    for (i=2; i<num_clus+2; i++) {
  1729. X                    /* if getfat returns zero */
  1730. X        if (!getfat(i))
  1731. X            total += clus_size;
  1732. X    }
  1733. X    return(total);
  1734. X}
  1735. SHAR_EOF
  1736. if test 4372 -ne "`wc -c < 'mdir.c'`"
  1737. then
  1738.     echo shar: "error transmitting 'mdir.c'" '(should have been 4372 characters)'
  1739. fi
  1740. fi
  1741. exit 0
  1742. #    End of shell archive
  1743.  
  1744. -- 
  1745.  
  1746. Rich $alz
  1747. Cronus Project, BBN Labs            rsalz@bbn.com
  1748. Moderator, comp.sources.unix            sources@uunet.uu.net
  1749.